package com.nulldev.util.security.encryptAPI.impls.ice_thirdparty;

import com.nulldev.util.VariableAPI.ByteUtil;
import com.nulldev.util.data.Variables;
import com.nulldev.util.data.Base64.Base64;
import com.nulldev.util.security.encryptAPI.Encryptor;
import com.nulldev.util.security.encryptAPI.impls.ice_thirdparty.IceKey.Levels;

public class Ice extends Encryptor {
	private final IceKey aes;

	public Ice(final String key) {
		this(key.getBytes());
	}

	public Ice(final String key, final Levels level) {
		this(key.getBytes(), level);
	}

	public Ice(final byte[] key) {
		this(key, Levels.LEVEL_2);
	}

	public Ice(final byte[] key, final Levels level) {
		super("encryptapi.tp.ice", new String[]
			{ "ICE", "ICe" }, key);
		this.aes = new IceKey(level.value());
		this.aes.set(key);
	}

	@Override
	public byte[] encryptToBytes(Object o) {
		Variables.notNullE(o);
		if (o instanceof byte[]) {
			// byte[] output = new byte[((byte[])o).length];
			byte[] output = new byte[0];
			byte[] buffer = new byte[8];
			for (final byte[] split : ByteUtil.divideArray((byte[]) o, 8)) {
				this.aes.encrypt(split, buffer);
				output = ByteUtil.concatenateByteArrays(output, buffer);
			}
			return output;
		} else if (o instanceof String) {
			byte[] output = new byte[0];
			byte[] buffer = new byte[8];
			for (final byte[] split : ByteUtil.divideArray(((String) o).getBytes(), 8)) {
				this.aes.encrypt(split, buffer);
				output = ByteUtil.concatenateByteArrays(output, buffer);
			}
			return output;
		} else {
			throw new UnsupportedOperationException("encryptToBytes() -> Unsupported operation on: " + o);
		}
	}

	@Override
	public String encrypt(Object o) {
		Variables.notNullE(o);
		if (o instanceof byte[]) {
			byte[] output = new byte[0];
			byte[] buffer = new byte[8];
			for (final byte[] split : ByteUtil.divideArray((byte[]) o, 8)) {
				this.aes.encrypt(split, buffer);
				output = ByteUtil.concatenateByteArrays(output, buffer);
			}
			return Base64.encodeBase64String(output);
		} else if (o instanceof String) {
			byte[] output = new byte[0];
			byte[] buffer = new byte[8];
			for (final byte[] split : ByteUtil.divideArray(((String) o).getBytes(), 8)) {
				this.aes.encrypt(split, buffer);
				output = ByteUtil.concatenateByteArrays(output, buffer);
			}
			return Base64.encodeBase64String(output);
		} else {
			throw new UnsupportedOperationException("encrypt() -> Unsupported operation on: " + o);
		}
	}

	@Override
	public String decrypt(String o) {
		Variables.notNullE(o);
		if (o.isEmpty())
			throw new IllegalArgumentException("o is empty!");
		byte[] output = new byte[0];
		byte[] buffer = new byte[8];
		for (final byte[] split : ByteUtil.divideArray(Base64.decodeBase64(o), 8)) {
			this.aes.decrypt(split, buffer);
			output = ByteUtil.concatenateByteArrays(output, buffer);
		}
		return new String(output);
	}

	@Override
	public byte[] decryptToBytes(byte[] o) {
		Variables.notNullE(o);
		if (o instanceof byte[]) {
			byte[] output = new byte[0];
			byte[] buffer = new byte[8];
			for (final byte[] split : ByteUtil.divideArray((byte[]) o, 8)) {
				this.aes.decrypt(split, buffer);
				output = ByteUtil.concatenateByteArrays(output, buffer);
			}
			return output;
		} else {
			throw new UnsupportedOperationException("encryptToBytes() -> Unsupported operation on: " + o);
		}
	}

	@Override
	public byte[] getKey() {
		return this.key;
	}

	@Override
	public String getKeyAsString() {
		return Base64.encodeBase64String(this.key);
	}
}
